/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */

import { Report } from '../common/report/report.js';
import { ReportListener } from '../common/report/report-listener.js';
import { ReportServiceImpl } from '../common/report/report-service-impl.js';
import { MetricCacheService } from '../internal/cache/service/metric-cache-service.js';

import { BaseEvent, MetricEventType } from './event/base-event.js';
import { DurationEvent, DurationEventState } from './event/duration-event.js';
import { LogEvent, MetricLogType } from './event/log-event.js';

/**
 * 矩阵服务
 *
 * @since 2022/8/17
 */
export class MetricService implements ReportListener {
  private static instance: MetricService;

  private metricCacheService: MetricCacheService;

  private constructor() {
    this.metricCacheService = MetricCacheService.getInstance();
  }

  /**
   * 提交metric到缓存服务
   *
   * @param event
   */
  submit(event: BaseEvent): void {
    this.metricCacheService.add(event);
  }

  getEventById(id?: string): BaseEvent | undefined {
    if (!id) {
      return undefined;
    }
    return this.metricCacheService.get(id);
  }

  /**
   * 供报告服务查询报告
   */
  queryReport(): Report<BaseEvent[]> {
    let events = this.filterDurationEvent(this.metricCacheService.getEvents());
    events = this.filterLogEvent(events);
    return new Report('events', events);
  }

  filterDurationEvent(events: BaseEvent[]): BaseEvent[] {
    return events.filter((event) => {
      if (event.getType() === MetricEventType.DURATION) {
        const durationEvent = event as DurationEvent;
        if (durationEvent.additional.state === DurationEventState.CREATED) {
          return false;
        }
      }
      return true;
    });
  }

  filterLogEvent(events: BaseEvent[]): BaseEvent[] {
    return events.filter((event) => {
      if (event.getType() === MetricEventType.LOG) {
        const logEvent = event as LogEvent;
        const durationEvent = this.getEventById(logEvent.additional.durationId) as DurationEvent;
        if (durationEvent && durationEvent.additional.state === DurationEventState.CREATED) {
          return false;
        }
        if (logEvent.additional.logType === MetricLogType.DETAIL && !durationEvent) {
          return false;
        }
      }
      return true;
    });
  }

  /**
   * 清除缓存
   */
  clear() {
    this.metricCacheService.close();
  }

  static getInstance() {
    if (!MetricService.instance) {
      MetricService.instance = new MetricService();
      ReportServiceImpl.getInstance().addListener(MetricService.instance);
    }
    return MetricService.instance;
  }
}
